home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1993 / MacHack 1993.toast / MacHack™ 1987-1992 / MacHack™ '90 / Source Code ƒ / C++ Files / HString.c next >
Encoding:
Text File  |  1990-05-14  |  8.6 KB  |  273 lines  |  [TEXT/QED1]

  1. // Copyright 1990 Waldemar Horwat.
  2. // Permission is granted for noncommercial use of this code.
  3.  
  4. #include <Types.h>
  5. #include <Memory.h>
  6. #include <OSUtils.h>
  7. #include <String.h>
  8. #include <Errors.h>
  9. #include "HString.h"
  10.  
  11.  
  12. OSErr String::err=0;
  13.  
  14. /*——————————————————————————————————————————————————————————————————————————————————————*/
  15. /* Copy src to this without deallocating whatever was in this previously.        */
  16. /*——————————————————————————————————————————————————————————————————————————————————————*/
  17. void String::internalCopy(const String &src)
  18.   {
  19.   if (data=src.data) data->refCount++;
  20.   }
  21.  
  22.  
  23. /*——————————————————————————————————————————————————————————————————————————————————————*/
  24. /* Copy cString to this without deallocating whatever was in this previously.        */
  25. /*——————————————————————————————————————————————————————————————————————————————————————*/
  26. OSErr String::internalCopy(const char *cString)
  27.   {
  28.   int length=strlen(cString);
  29.  
  30.   if (data=(StringData *)NewHandle(length+5))
  31.     {
  32.     data->refCount=1;
  33.     BlockMove(Ptr(cString),data->str,length+1);
  34.     return 0;
  35.     }
  36.   return String::err=memFullErr;
  37.   }
  38.  
  39.  
  40. /*——————————————————————————————————————————————————————————————————————————————————————*/
  41. /* Make sure that this String's data is not shared with any other String.  This        */
  42. /* function should be called before this String's data is altered.            */
  43. /*——————————————————————————————————————————————————————————————————————————————————————*/
  44. OSErr String::fresh()
  45.   {
  46.   OSErr err;
  47.  
  48.   if (!data || data->refCount<=1) return 0;
  49.   StringData *data2=data;
  50.   if (err=HandToHand((Handle *)&data2)) return String::err=err;
  51.   data->refCount--;
  52.   data2->refCount=1;
  53.   data=data2;
  54.   return 0;
  55.   }
  56.  
  57.  
  58. /*——————————————————————————————————————————————————————————————————————————————————————*/
  59. /* Deallocate this String.  Deallocate the data too if its reference count reaches    */
  60. /* zero.                                        */
  61. /*——————————————————————————————————————————————————————————————————————————————————————*/
  62. String::~String()
  63.   {
  64.   if (data && !(--data->refCount))
  65.     DisposHandle(Handle(data));
  66.   }
  67.  
  68.  
  69. /*——————————————————————————————————————————————————————————————————————————————————————*/
  70. /* Clear this String to a null string.                            */
  71. /*——————————————————————————————————————————————————————————————————————————————————————*/
  72. void String::clear()
  73.   {
  74.   this->String::~String();
  75.   data=0;
  76.   }
  77.  
  78.  
  79. /*——————————————————————————————————————————————————————————————————————————————————————*/
  80. /* Assign src to this.  Deallocate the old String in this.                */
  81. /*——————————————————————————————————————————————————————————————————————————————————————*/
  82. String &String::operator=(const String &src)
  83.   {
  84.   if (this!=&src) //Handle a String assigned to itself correctly!
  85.     {
  86.     this->String::~String();
  87.     internalCopy(src);
  88.     }
  89.   return *this;
  90.   }
  91.  
  92.  
  93. /*——————————————————————————————————————————————————————————————————————————————————————*/
  94. /* Assign the cString to this.  Deallocate the old String in this.            */
  95. /*——————————————————————————————————————————————————————————————————————————————————————*/
  96. OSErr String::operator=(const char *cString)
  97.   {
  98.   this->String::~String();
  99.   return internalCopy(cString);
  100.   }
  101.  
  102.  
  103. /*——————————————————————————————————————————————————————————————————————————————————————*/
  104. /* Return the length of this String.                            */
  105. /*——————————————————————————————————————————————————————————————————————————————————————*/
  106. int String::length() const
  107.   {
  108.   if (!data) return 0;
  109.   return strlen(data->str);
  110.   }
  111.  
  112.  
  113. /*——————————————————————————————————————————————————————————————————————————————————————*/
  114. /* Return the character at position index in this String.  Return the null character if    */
  115. /* index is out of bounds.                                */
  116. /*——————————————————————————————————————————————————————————————————————————————————————*/
  117. char String::operator[](int index) const
  118.   {
  119.   if (!data || index<0 || index>=strlen(data->str)) return 0;
  120.   return data->str[index];
  121.   }
  122.  
  123.  
  124. /*——————————————————————————————————————————————————————————————————————————————————————*/
  125. /* Return the substring of the given length starting from the given offset.  The null    */
  126. /* string is returned if the offset is out of bounds.  The String returned may be    */
  127. /* shorter than length characters if offset+length exceeds the length of this String.    */
  128. /*——————————————————————————————————————————————————————————————————————————————————————*/
  129. String String::substr(int offset, int length) const
  130.   {
  131.   String result; //Defaults to null.
  132.   int thisLength=String::length();
  133.  
  134.   if (offset>=0 && offset<thisLength)
  135.     {
  136.     if (offset+length>=thisLength) length=thisLength-offset;
  137.     if (result.data=(StringData *)NewHandle(length+5))
  138.       {
  139.       result.data->refCount=1;
  140.       BlockMove(data->str+offset,result.data->str,length);
  141.       result.data->str[length]='\0';
  142.       }
  143.     }
  144.   return result;
  145.   }
  146.  
  147.  
  148. /*——————————————————————————————————————————————————————————————————————————————————————*/
  149. /* Return the contents of this String as a C string.  The result may move the next time    */
  150. /* memory is allocated!                                    */
  151. /*——————————————————————————————————————————————————————————————————————————————————————*/
  152. char *String::cString() const
  153.   {
  154.   if (!data) return "";
  155.   return data->str;
  156.   }
  157.  
  158.  
  159. /*——————————————————————————————————————————————————————————————————————————————————————*/
  160. /* Return true if the Strings are exactly equal.                    */
  161. /*——————————————————————————————————————————————————————————————————————————————————————*/
  162. bool String::operator==(const String &src2) const
  163.   {
  164.   if (!data || !src2.data)
  165.     return length()==src2.length();
  166.   return !strcmp(data->str,src2.data->str);
  167.   }
  168.  
  169.  
  170. /*——————————————————————————————————————————————————————————————————————————————————————*/
  171. /* Concatenate this and src to yield a new String.                    */
  172. /*——————————————————————————————————————————————————————————————————————————————————————*/
  173. String String::operator|(const String &src) const
  174.   {
  175.   String result=*this;
  176.   result|=src;
  177.   return result;
  178.   }
  179.  
  180.  
  181. /*——————————————————————————————————————————————————————————————————————————————————————*/
  182. /* Destructively concatenate src to the end of this.                    */
  183. /*——————————————————————————————————————————————————————————————————————————————————————*/
  184. OSErr String::operator|=(const String &src)
  185.   {
  186.   OSErr err;
  187.  
  188.   int srcLength=src.length();
  189.   if (!srcLength) return 0; // Nothing to concatenate?
  190.   if (!data)
  191.     {
  192.     internalCopy(src);
  193.     return 0;
  194.     }
  195.   if (err=fresh()) return err;
  196.   SetHandleSize(Handle(data),GetHandleSize(Handle(data))+srcLength);
  197.   if (err=MemError()) return String::err=err;
  198.   strcat(data->str,src.data->str);
  199.   return 0;
  200.   }
  201.  
  202.  
  203. /*——————————————————————————————————————————————————————————————————————————————————————*/
  204. /* Destructively concatenate ch to the end of this.                    */
  205. /*——————————————————————————————————————————————————————————————————————————————————————*/
  206. OSErr String::operator|=(char ch)
  207.   {
  208.   char cString[2];
  209.  
  210.   cString[0]=ch;
  211.   cString[1]='\0';
  212.   return *this|=cString;
  213.   }
  214.  
  215.  
  216. /*——————————————————————————————————————————————————————————————————————————————————————*/
  217. /* Destructively concatenate cString to the end of this.                */
  218. /*——————————————————————————————————————————————————————————————————————————————————————*/
  219. OSErr String::operator|=(char *cString)
  220.   {
  221.   OSErr err;
  222.  
  223.   int srcLength=strlen(cString);
  224.   if (!srcLength) return 0; // Nothing to concatenate?
  225.   if (!data)
  226.     {
  227.     internalCopy(cString);
  228.     return 0;
  229.     }
  230.   if (err=fresh()) return err;
  231.   SetHandleSize(Handle(data),GetHandleSize(Handle(data))+srcLength);
  232.   if (err=MemError()) return String::err=err;
  233.   strcat(data->str,cString);
  234.   return 0;
  235.   }
  236.  
  237.  
  238. /*——————————————————————————————————————————————————————————————————————————————————————*/
  239. /* Destructively concatenate ch to the beginning of this.                */
  240. /*——————————————————————————————————————————————————————————————————————————————————————*/
  241. OSErr String::operator^=(char ch)
  242.   {
  243.   char cString[2];
  244.  
  245.   cString[0]=ch;
  246.   cString[1]='\0';
  247.   return *this^=cString;
  248.   }
  249.  
  250.  
  251. /*——————————————————————————————————————————————————————————————————————————————————————*/
  252. /* Destructively concatenate cString to the beginning of this.                */
  253. /*——————————————————————————————————————————————————————————————————————————————————————*/
  254. OSErr String::operator^=(char *cString)
  255.   {
  256.   OSErr err;
  257.  
  258.   int srcLength=strlen(cString);
  259.   if (!srcLength) return 0; // Nothing to concatenate?
  260.   if (!data)
  261.     {
  262.     internalCopy(cString);
  263.     return 0;
  264.     }
  265.   if (err=fresh()) return err;
  266.   Size dataSize=GetHandleSize(Handle(data));
  267.   SetHandleSize(Handle(data),dataSize+srcLength);
  268.   if (err=MemError()) return String::err=err;
  269.   BlockMove(data->str,data->str+srcLength,dataSize-4);
  270.   BlockMove(cString,data->str,srcLength);
  271.   return 0;
  272.   }
  273.